import 'dart:async';
import 'dart:io';
import 'package:flame/components.dart';
import 'package:flame/effects.dart';
import 'package:flame/flame.dart';
import 'package:freedom/entity/restful.dart';
import 'package:freedom/page/mahjong/bloc/user_state.dart';
import 'package:freedom/page/mahjong/common/card_build.dart';
import 'package:freedom/page/mahjong/common/common_card.dart';
import 'package:freedom/page/mahjong/common/mahjong_context.dart';
import 'package:freedom/page/mahjong/common/message_content.dart';
import 'package:freedom/page/mahjong/event/user_reflash_action.dart';
import 'package:freedom/page/mahjong/event/user_select_card.dart';
import 'package:freedom/page/mahjong/hand_area/abstract_card_area.dart';
import 'package:freedom/page/mahjong/mahjong_game.dart';
import 'package:freedom/page/mahjong/message/action_message.dart';
import 'package:freedom/page/mahjong/util/mahjong_util.dart';
import 'package:freedom/page/mahjong/util/user_location.dart';
import 'package:freedom/util/api_router.dart';
import 'package:freedom/util/card_util.dart';
import 'package:freedom/util/http.dart';
import 'package:freedom/util/voice_message_sound.dart';

class BottomCardArea extends AbstractHand with HasGameRef<MahjongIndexGame> {
  var mjBgImage = Flame.images.fromCache('mahjong/user/top/usercard.png');

  bool swapUserCard = false;

  CommonCard? _exportCard;

// 需要出什么牌 能胡什么牌 都在这里了
  List<CardEHInfo> _cardEHInfoList = [];
  BottomCardArea()
      : super(
            size: MahjongContext().bottomHandCardAreaSize,
            position: MahjongContext().bottomHandCardAreaPoint);

  @override
  FutureOr<void> onLoad() {}

  @override
  Direction userDirection() {
    return Direction.BOTTOM;
  }

  void initUserHuCardTips() {}

  bool cardClickAction(CommonCard current) {
    //事件处理
    if (currentUserState.checkWaitActionExits(ActionMessageHandler.EXCHANGE)) {
      //如果是交换 用户只能选3张一样的
      if (!current.selected) {
        HAND_CARD_SELECT.add(current);
      } else {
        HAND_CARD_SELECT.remove(current);
      }
    } else {
      List<int> userAllCards = currentUserState.getUserHandCards();
      MahjongContext().reInitHuCardTips(true,
          userAllCards: userAllCards,
          exportCard: current.cardCode,
          checkHave: true);
      if (current.selected && userAllCards.length % 3 == 2) {
        // 出牌事件
        var data = MessageContent<List<MahjongMessage>>(
            messageFromUid: 1,
            type: MessageContent.MT_ACT,
            body: [
              MahjongMessage(
                  type: ActionMessageHandler.EXPORT, cardCode: current.cardCode)
            ]).toJson();
        _exportCard = current;

        Http.getInstance().request<Restful>(ApiRouter.roomMessage,
            contentType: ContentType.json,
            type: RequestEnum.POST,
            showErrorMsg: true,
            data: data, success: (data) {
          MahjongContext().reInitHuCardTips(false);
          MahjongContext.postRoomEvent(UserSelectCardEvent(null));
          MahjongContext.postUserEvent<UserReflashActionEvent>(
              MahjongContext.currentUser!.userId, UserReflashActionEvent([]));
        });
        return true;
      } else {
        // 取消其他牌的状态
        children
            .where((element) => element is CommonCard && element != current)
            .forEach((element) {
          if (element is CommonCard) {
            element.cardSelect(false);
          }
        });
      }
    }
    bool result = !current.selected;
    // 取消桌面其它牌的选中状态
    MahjongContext.postRoomEvent(
        UserSelectCardEvent(result ? current.cardCode : null));
    return result;
  }

  bool checkFocus(UserState userStateParam, int cardCode) {
    // 构建手里面牌的时候  决定这张牌是否可点击
    bool focus = false;
    //如果报听了 然后又出了牌了
    if (currentUserState.listen &&
        currentUserState.listenCardArray!.length % 3 == 1) {
      focus = true;
    } else if (currentUserState.listen &&
        currentUserState.listenCardArray!.length % 3 == 2) {
      // 如果报听了   又没出牌   出了过后用户必须 还能下叫
      focus = !_cardEHInfoList.any((card) => card.exportCard == cardCode);
    }
    return focus;
  }

  @override
  Future<void> reflashUI(UserState userStateParam,
      {List<int>? highlight}) async {
    currentUserState = userStateParam;
    /**
      * 构建用户手牌
      */
    if (game.record == null) {
      _cardEHInfoList =
          MahjongUtil.checkHuCard(currentUserState.getUserHandCards(), 0);
    }
    HAND_CARD_SELECT = {};
    removeAll(Set.from(children));
    double currentX = size.x - MahjongContext().bottomHandCard.x;
    // 判断用户是否有没有交换事件 ，我觉得这样 做 没啥意义  再来个事件????
    if (currentUserState.checkWaitActionExits(ActionMessageHandler.EXCHANGE) &&
        !MahjongContext().getPlayback) {
      MahjongContext().showOverlay(MahjongOverlay.swapCardTipsDialog);
    } else {
      MahjongContext().closeOverlay(MahjongOverlay.swapCardTipsDialog);
    }

    int? touchCard = currentUserState.touchCard;
    // 不要添加手牌,手牌单独处理
    List<int> userHandCards =
        currentUserState.getUserHandCards(addTouch: false);
    // 判断用户的手牌数量
    int length = userHandCards.isNotEmpty
        ? userHandCards.length - 1
        : currentUserState.handCardCount;

    currentX -= MahjongContext().bottomHandCard.x * 1.3;
    //下面已经决定了位置
    double inAreaTime = 1.0;
    if (currentUserState.startGaming) {
      VoiceMessageSound().play("SHUFFLE", close: () {});
    }
    while (length >= 0 && userHandCards.isNotEmpty) {
      // 构建手里面牌的时候  决定这张牌是否可点击
      bool focus = checkFocus(currentUserState, userHandCards[length]);
      double cardPointx = currentX + MahjongContext().bottomHandCard.x / 2;

      var cardPoint = Vector2(cardPointx, 0);
      if (currentUserState.startGaming) {
        cardPoint = Vector2(0, 0);
      }
      if (currentUserState.startGaming) {
        cardPoint.y = -MahjongContext().bottomHandCard.y / 4;
      }

      CommonCard card = CardBuildUtil.bottomHandCard(
          cardPoint, userHandCards[length],
          focus: focus,
          size: MahjongContext().bottomHandCard,
          showTips: currentUserState.win
              ? false
              : _cardEHInfoList
                  .any((card) => card.exportCard == userHandCards[length]),
          cardClick: cardClickAction);
      if (highlight != null && highlight.contains(userHandCards[length])) {
        card.cardSelect(true);
        highlight.remove(userHandCards[length]);
      }
      if (currentUserState.startGaming) {
        card.add(MoveToEffect(
            Vector2(cardPointx, 0), EffectController(duration: inAreaTime)));
        inAreaTime -= 0.1;
        if (inAreaTime <= 0) {
          inAreaTime = 0.1;
        }
      }
      add(card);
      currentX -= MahjongContext().bottomHandCard.x;
      length--;
    }

    // 是否添加手牌 两种情况
    if (!currentUserState.win) {
      if (currentUserState.touchCard != null) {
        addTouchCard(currentUserState.touchCard, highlight: highlight);
      } else if (userHandCards.isNotEmpty && userHandCards.length % 3 == 2) {
        touchCard = userHandCards[length];
        length = length - 1;
        addTouchCard(touchCard, highlight: highlight);
      }
    } else {
      addWinCard(currentUserState.winCard!);
    }
    currentX = currentX +
        MahjongContext().bottomHandCard.x +
        MahjongContext().bottomTBCardSize.x / 2;

    currentUserState.openDeal?.forEach((pItem) {
      // 获取是处理的谁的牌
      Direction? pointTo;
      if (pItem.targetUserSeq != null) {
        pointTo = LocationUtil.buildLocationUtil(
            MahjongContext.roomInfo.getUserCount(),
            currentUserState.seq,
            pItem.targetUserSeq!);
      }
      currentX -= MahjongContext().bottomTBCardSize.x / 2;
      var index = 0;

      pItem.cardList?.forEach((crt) {
        index++;
        currentX -= MahjongContext().bottomTBCardSize.x;
        // y轴上下居中
        var positionY = (size.y - MahjongContext().bottomTBCardSize.y) / 2;
        var showPointTo =
            (index == 3 && pItem.cardList!.length == 4) || index == 2;
        PositionComponent cardInfo;
        if (index == 3 && pItem.cardList!.length == 4) {
          currentX += MahjongContext().bottomTBCardSize.x;
          positionY -= MahjongContext().bottomTBCardSize.y *
              (1 - MahjongContext().exportDiagonalRatio);
          cardInfo = CardBuildUtil.bottomExport(
              Vector2(currentX, positionY), crt,
              pointTo: showPointTo ? pointTo : null,
              size: MahjongContext().bottomTBCardSize);
        } else if (pItem.type == 2) {
          cardInfo = CardBuildUtil.btDarkExport(Vector2(currentX, positionY),
              size: MahjongContext().bottomTBCardSize);
        } else {
          cardInfo = CardBuildUtil.bottomExport(
              Vector2(currentX, positionY), crt,
              pointTo: showPointTo ? pointTo : null,
              size: MahjongContext().bottomTBCardSize);
        }
        add(cardInfo);
      });
    });
  }

  @override
  void addWinCard(int card) {
    TOUCH_CARD?.removeFromParent();
    add(CardBuildUtil.bottomExport(
        Vector2(
            size.x -
                MahjongContext().bottomHandCard.x +
                MahjongContext().bottomHandCard.x / 2,
            0),
        card,
        pointTo: null,
        size: MahjongContext().bottomHandCard));
  }

  @override
  Vector2 getHandFirstCardPoint() {
    return Vector2(position.x + size.x - MahjongContext().bottomHandCard.x / 2,
        position.y);
  }

  /// 新增出牌
  @override
  Component? addTouchCard(int? cardCode, {List<int>? highlight}) {
    // 摸牌修改当前用户的状态 但是初始化数据的时候也在用
    // 数据库分为两列 一列手牌  一列摸牌
    // 当碰牌的时候 也会出现从手牌里面进行添加成为摸牌
    // 所以这里必须要做一层判断避免脏数据   这里本身是摸牌行为但是初始化数据的时候也有可能会从手牌里面初始化出来
    currentUserState.addTouchCard(cardCode);
    if (game.record == null) {
      _cardEHInfoList =
          MahjongUtil.checkHuCard(currentUserState.getUserHandCards(), 0);
    }
    for (var mahjongCard in children) {
      if (mahjongCard is! CommonCard) {
        continue;
      }
      if (!mahjongCard.handCard) {
        continue;
      }
      mahjongCard.showTips = _cardEHInfoList
              .any((card) => card.exportCard == mahjongCard.cardCode) &&
          !currentUserState.listen;
    }
    if (TOUCH_CARD != null) {
      TOUCH_CARD!.removeFromParent();
      TOUCH_CARD = null;
    }
    bool showTips = _cardEHInfoList.any((card) => card.exportCard == cardCode);
    // 构建手里面牌的时候  决定这张牌是否可点击
    bool focus = false;
    //如果报听了 然后又出了牌了
    if (currentUserState.listen &&
        currentUserState.listenCardArray!.length % 3 == 2) {
      // 如果报听了   又没出牌   出了过后用户必须 还能下叫
      focus = !_cardEHInfoList.any((card) => card.exportCard == cardCode);
    }
    var cardPoinit = Vector2(
        size.x -
            MahjongContext().bottomHandCard.x +
            MahjongContext().bottomHandCard.x / 2,
        currentUserState.touchCardAction || currentUserState.startGaming
            ? -MahjongContext().bottomHandCard.y / 4
            : 0);
    TOUCH_CARD = CardBuildUtil.bottomHandCard(cardPoinit, cardCode!,
        showTips: currentUserState.win ? false : showTips,
        focus: focus,
        cardClick: cardClickAction);
    (TOUCH_CARD as CommonCard)
        .cardSelect(highlight?.contains(cardCode) ?? false);
    if (currentUserState.touchCardAction || currentUserState.startGaming) {
      TOUCH_CARD!.add(MoveToEffect(
          Vector2(cardPoinit.x, 0),
          EffectController(
              duration: currentUserState.touchCardAction ? 0.3 : 1)));
    }
    add(TOUCH_CARD!);
    return TOUCH_CARD;
  }

  /// 对于其他人来说是exportCard
  /// 对于玩家来说这里应该是移除选中的牌

  @override
  void exportCard(int? card, {ExportCallBack? callBack}) {
    if (card == null) {
      return;
    }
    if ((_exportCard == null || _exportCard!.cardCode != card) &&
        children.isNotEmpty) {
      _exportCard = children.lastWhere((element) =>
          element is CommonCard &&
          element.handCard &&
          element.cardCode == card) as CommonCard;
    }
    if (_exportCard == null) {
      return;
    }
    // 如果用户报听了，然后报听的牌还是 满牌形式
    if ((currentUserState.listenCardArray?.length ?? 0) % 3 == 2) {
      Cardutil.removeCard(currentUserState.listenCardArray!, card);
    }
    Vector2 pointByScc =
        gameRef.bottomExportArea!.getLastPointByScc(_exportCard!.position);
    Effect effect = MoveByEffect(
      pointByScc,
      EffectController(duration: 0.3),
    );
    _exportCard!.addAll([
      effect,
      ScaleEffect.by(
        Vector2.all(0.6),
        EffectController(duration: 0.3),
      )
    ]);
    effect.onComplete = () {
      /**
             * 当出牌动画执行完毕后
             * 1. 移出调打出的牌
             * 2. 将桌面的选中的牌状态重置
             * 3. 重新初始化用户手牌
             */
      _exportCard!.removeFromParent();
      gameRef.bottomExportArea!.defaultExportCard(_exportCard!.cardCode);
      reflashUI(currentUserState);
      _exportCard = null;
      if (callBack != null) {
        callBack(gameRef.bottomExportArea!.eportAllCard);
      }
    };
    return;
  }

  @override
  void addSwapCard(List<int>? swapCard) {
    if (swapCard == null || swapCard.isEmpty) {
      return;
    }
    currentUserState.addSwapCard(swapCard);
    reflashUI(currentUserState, highlight: swapCard).then((value) {
      Future.delayed(const Duration(seconds: 1), () {
        // 添加完毕牌后 将所有高亮手牌变不亮 哈哈
        for (var cardItem in children) {
          if (cardItem is CommonCard) {
            cardItem.cardSelect(false);
          }
        }
      });
    });
  }

  @override
  void removeCard(int exportCard) {
    if (currentUserState.getUserHandCards().length % 3 == 2) {
      currentUserState.removeAssignCard([exportCard]);
    }
    reflashUI(currentUserState);
  }
}
